package com.shinvent.security;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/**
 * This program generates a AES key, retrieves its raw bytes, and then
 * reinstantiates a AES key from the key bytes. The reinstantiated key is used
 * to initialize a AES cipher for encryption and decryption.
 */

public class AES {
	/**
	 * Turns array of bytes into string
	 * 
	 * @param buf	Array of bytes to convert to hex string
	 * @return 		Generated hex string
	 */
	public static String asHex(byte buf[]) {
		StringBuffer strbuf = new StringBuffer(buf.length * 2);
		int i;

		for (i = 0; i < buf.length; i++) {
			if (((int) buf[i] & 0xff) < 0x10)
				strbuf.append("0");

			strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
		}

		return strbuf.toString();
	}

	private static byte[] hexByte(final String encoded) {
	    if ((encoded.length() % 2) != 0)
	        throw new IllegalArgumentException("Input string must contain an even number of characters");

	    final byte result[] = new byte[encoded.length()/2];
	    final char enc[] = encoded.toCharArray();
	    for (int i = 0; i < enc.length; i += 2) {
	        StringBuilder curr = new StringBuilder(2);
	        curr.append(enc[i]).append(enc[i + 1]);
	        result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
	    }
	    return result;
	}

	public static void main(String args[]) {
		try {
			AES aes = new AES();
			String pass = "3597a1b3c011eda3b49cca124d4d4e19";
			String message = "Hello, World! Hola España!";
			aes.encrypt(pass, message);

			String messageEn = "895776c0cd36d535f10e5eca56d928c2acb67c4129b2ffdb215def2c08bdf110";
			aes.decrypt(pass, messageEn);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public String encrypt(String pass, String message) throws Exception {
		byte[] keyMaterial = hexByte(pass);
		SecretKeySpec key = new SecretKeySpec(keyMaterial, "AES");
		// encrypting
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, key);
		byte[] plaintext = message.getBytes("UTF-8");
		byte[] ciphertext = cipher.doFinal(plaintext);
		System.out.println("Msg encrypted:\n" +asHex(ciphertext));
		return asHex(ciphertext);
	}

	public String decrypt(String pass, String message) throws Exception {
		byte[] keyMaterial = hexByte(pass);
		SecretKeySpec key = new SecretKeySpec(keyMaterial, "AES");
		// decrypting
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.DECRYPT_MODE, key);
		byte[] original = cipher.doFinal(hexByte(message));
		String originalString = new String(original,"UTF-8");
		System.out.println("Msg decrypted:\n"+originalString);
		return originalString;
	}
}
